1 /** 2 * License: 3 * Copyright Devisualization (Richard Andrew Cattermole) 2014 - 2017. 4 * Distributed under the Boost Software License, Version 1.0. 5 * (See accompanying file LICENSE_1_0.txt or copy at 6 * http://www.boost.org/LICENSE_1_0.txt) 7 */ 8 module devisualization.util.core.text; 9 import std..string : indexOf, toUpper, toLower; 10 import std.traits : isSomeString; 11 12 /** 13 * Replaces some text in a string. 14 * 15 * Params: 16 * text = The old text to replace from 17 * oldText = The text to remove 18 * newText = The text to replace oldText with 19 * caseSensitive = Does 'A' and 'a' the same character? Default: true 20 * first = Stop after the first instance of oldText? Default: false 21 * 22 * Returns: 23 * The text that has been replaced 24 */ 25 deprecated("Too memory expensive, requires a rewrite.") 26 T replace(T)(T text, T oldText, T newText, bool caseSensitive = true, bool first = false) pure if (isSomeString!T) { 27 T ret; 28 T tempData; 29 bool stop; 30 foreach(dchar c; text) { 31 if (tempData.length > oldText.length && !stop) { 32 ret ~= tempData; 33 tempData.length = 0; 34 } 35 if (((oldText[0 .. tempData.length] != tempData && caseSensitive) || (oldText[0 .. tempData.length].toLower() != tempData.toLower() && !caseSensitive)) && !stop) { 36 ret ~= tempData; 37 tempData.length = 0; 38 } 39 tempData ~= c; 40 if (((tempData == oldText && caseSensitive) || (tempData.toLower() == oldText.toLower() && !caseSensitive)) && !stop) { 41 ret ~= newText; 42 tempData.length = 0; 43 stop = first; 44 } 45 } 46 if (tempData != T.init) { 47 ret ~= tempData; 48 } 49 return ret; 50 } 51 52 unittest { 53 string test = "Hello World!"; 54 test = test.replace("Hello", "Hi"); 55 assert(test == "Hi World!"); 56 57 assert(replace("Hello World!", "o", "a") == "Hella Warld!"); 58 assert(replace("Hello World!", "!", "#") == "Hello World#"); 59 } 60 61 /** 62 * Split a string by a delimater 63 * 64 * Params: 65 * text = The text to split from 66 * delimater = The text to split by 67 * 68 * Returns: 69 * An array of text that has been split 70 */ 71 deprecated("Use std.algorithm.iteration : splitter instead.") 72 pure T[] split(T)(T text, T delimater) if (isSomeString!T) { 73 T[] ret; 74 ptrdiff_t i; 75 while((i = text.indexOf(delimater)) >= 0) { 76 ret ~= text[0 .. i]; 77 text = text[i + delimater.length .. $]; 78 } 79 if (text.length > 0) { 80 ret ~= text; 81 } 82 return ret; 83 } 84 85 unittest { 86 string test = "abcd|efgh|ijkl"; 87 assert(test.split("|") == ["abcd", "efgh", "ijkl"]); 88 string test2 = "abcd||efgh||ijkl"; 89 assert(test2.split("||") == ["abcd", "efgh", "ijkl"]); 90 } 91 92 /** 93 * Multiplies a string by itself and concactenates it onto the resulting string 94 * 95 * Similar to how Python's string multiplication works. 96 * 97 * Params: 98 * text = The text to multiply 99 * count = How many times to multiply it 100 * 101 * Returns: 102 * The multiplied string 103 */ 104 T multiply(T)(T text, size_t count) pure @safe nothrow if (isSomeString!T) { 105 alias U = typeof(cast()T.init[0]); 106 U[] ret; 107 ret.length = text.length * count; 108 109 size_t j; 110 foreach(i; 0 .. count) { 111 ret[j .. j + text.length] = text[]; 112 j += text.length; 113 } 114 115 return ret; 116 } 117 118 unittest { 119 assert(" ".multiply(3) == " "); 120 assert("hello ".multiply(2) == "hello hello "); 121 assert("boo".multiply(1) == "boo"); 122 assert("huh".multiply(0) == ""); 123 } 124 125 /** 126 * Gets a string which has been indented to x spaces. 127 * Uses four spaces, not tabs. 128 * 129 * Params: 130 * count = How many times to indent it 131 * 132 * Returns: 133 * The indented string 134 */ 135 string getSpaceIndent(size_t count) pure @safe nothrow { 136 return " ".multiply(count); 137 }